package com.clp.protocol.iec104.iec104.definition;

import com.clp.protocol.iec104.iec104.apdu.UApdu;
import com.clp.protocol.iec104.iec104.apdu.apci.UApci;
import com.clp.protocol.iec104.iec104.apdu.apci.UCtrlArea;
import com.clp.util.ByteUtil;
import com.clp.util.exception.EnumElemDoesNotExistException;
import io.netty.buffer.ByteBuf;
import lombok.Getter;

/**
 * U帧控制类型
 */
@Getter
public enum UCtrlType {
    /**
     * 启动传输激活
     */
    U_START_DT_V(new byte[]{0x07, 0x00, 0x00, 0x00}, "启动传输激活"),
    /**
     * 启动传输确认
     */
    U_START_DT_C(new byte[]{0x0B, 0x00, 0x00, 0x00}, "启动传输确认"),
    /**
     * 停止传输激活
     */
    U_STOP_DT_V(new byte[]{0x13, 0x00, 0x00, 0x00}, "停止传输激活"),
    /**
     * 停止传输确认
     */
    U_STOP_DT_C(new byte[]{0x23, 0x00, 0x00, 0x00}, "停止传输确认"),
    /**
     * 链路测试激活
     */
    U_TEST_FR_V(new byte[]{0x43, 0x00, 0x00, 0x00}, "链路测试激活"),
    /**
     * 链路测试确认
     */
    U_TEST_FR_C(new byte[]{(byte) 0x83, 0x00, 0x00, 0x00}, "链路测试确认");

    private final byte[] uCtrlBytes; // 对应类型的控制域
    private final String desc;
    private final UApdu singletonUApdu;

    UCtrlType(byte[] uCtrlBytes, String desc) {
        this.uCtrlBytes = uCtrlBytes;
        this.desc = desc;
        this.singletonUApdu = new SingletonUApdu(this);
    }

    /**
     * 获取单例的 UApdu
     * @return
     */
    public UApdu getSingletonUApdu() {
        return singletonUApdu;
    }

    private static class SingletonUApdu extends UApdu {
        public SingletonUApdu(UCtrlType uCtrlType) {
            super(new UApci(ConstVal.HEAD_VAL, ConstVal.APCI_LEN, new UCtrlArea(uCtrlType)));
        }

        @Override
        public UApdu refreshFrom(ByteBuf buf) {
            throw new UnsupportedOperationException("单例的UApdu无法初始化！");
        }
    }

    /**
     * 如果控制域代表U帧，那么就返回控制类型
     *
     * @return
     */
    public static UCtrlType gain(byte[] uCtrlBytes) {
        for (UCtrlType uCtrlType : UCtrlType.values()) {
            if (ByteUtil.isSameBytes(uCtrlType.getUCtrlBytes(), uCtrlBytes)) {
                return uCtrlType;
            }
        }
        throw new EnumElemDoesNotExistException(UCtrlType.class);
    }
}
